package com.songcha.library_common.ui.view

import android.content.Context
import android.content.res.Configuration
import android.graphics.*
import android.graphics.drawable.GradientDrawable
import android.util.AttributeSet
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.widget.HorizontalScrollView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.get
import androidx.core.view.size
import androidx.viewpager.widget.ViewPager
import com.songcha.library_common.R
import com.songcha.library_common.util.*

class CustomTabLayout
    @JvmOverloads
    constructor(
        context: Context,
        attrs: AttributeSet?=null,
        defStyle: Int=0,
        defRes:Int=0,
    )
    : HorizontalScrollView(context,attrs,defStyle,defRes) {
    private lateinit var mTabsContainer:LinearLayout
    private var mViewPager:ViewPager?=null
    private var mTitles:MutableList<String> = mutableListOf()
    private var mEvenWidth=true
    private var mEvenWidthAttr=true
    private var mTabWidth=0f
    private var mTabHeight=0f
    private var mCurrentPosition=0
    private var mPositionOffset=0f
    private var mTitleColor=Color.BLACK
    private var mTitleSize=0f
    private var mTitleSelectColor=Color.BLACK
    private var mTitleSelectSize=0f
    private var mShowIndicator=true
    private var mIndicatorHeight=0f
    private var mIndicatorRadius=0f
    private var mIndicatorMarginTop=0f
    private var mIndicatorMarginBottom=0f
    private var mTabBackGroundColor=Color.TRANSPARENT
    private var mTabSelectBackGroundColor=Color.TRANSPARENT
    private var mTabsContainerHeight=0
    private var mIndicatorDrawable=GradientDrawable()
    private var mSelectBackGroundDrawable=GradientDrawable()
    private var mTabCount=0
    private var mIndicatorWidthEqualTitle=true
    private var mIndicatorBounds=Rect()
    private var mSelectBackGroundBounds=Rect()
    private var mIndicatorWidth=0f
    private var mDefaultTextSize=0f
    private var mDefaultIndicatorHeight=6f
    private var mIndicatorColor=Color.BLUE
    private var mLandWidthSize=0// width on portrait,prohibit reset size when landscape
    private var mTipsDefaultSize=16f
    private var mTipsTextSize=12f
    private var mTabPadddingLeft=0f
    private var mTabPadddingRight=0f

    private var mPageChangeListener:((Int)->Unit)?=null

    init {
        initView(context,attrs)
    }

    private fun initView(context:Context,attrs: AttributeSet?){

        setWillNotDraw(false)

        if(attrs!=null){
            val ta=context.obtainStyledAttributes(attrs, R.styleable.CustomTabLayout)
            mEvenWidthAttr=ta.getBoolean(R.styleable.CustomTabLayout_even_width,true)
            mEvenWidth=mEvenWidthAttr
            mTabWidth=ta.getDimension(R.styleable.CustomTabLayout_tab_width,0f)
            if(mTabWidth>0){
                mEvenWidth=false
            }
            mTabHeight=ta.getDimension(R.styleable.CustomTabLayout_tab_height,0f)

            mTitleColor=ta.getColor(R.styleable.CustomTabLayout_title_color,Color.BLACK)
            mTitleSelectColor=ta.getColor(R.styleable.CustomTabLayout_title_select_color,Color.BLACK)
            mTitleSize=ta.getDimension(R.styleable.CustomTabLayout_title_size,0f)
            mTitleSelectSize=ta.getDimension(R.styleable.CustomTabLayout_title_select_size,0f)
            mTabBackGroundColor=ta.getColor(R.styleable.CustomTabLayout_tab_background_color,Color.TRANSPARENT)
            mTabSelectBackGroundColor=ta.getColor(R.styleable.CustomTabLayout_tab_select_background_color,Color.TRANSPARENT)

            mShowIndicator=ta.getBoolean(R.styleable.CustomTabLayout_show_indicator,true)
            mIndicatorHeight=ta.getDimension(R.styleable.CustomTabLayout_indicator_height,0f)
            if(mShowIndicator && mIndicatorHeight==0f){
                mIndicatorHeight=mDefaultIndicatorHeight.dp2px()
            }
            mIndicatorRadius=ta.getDimension(R.styleable.CustomTabLayout_indicator_radius,0f)
            mIndicatorMarginTop=ta.getDimension(R.styleable.CustomTabLayout_indicator_marginTop,0f)
            mIndicatorMarginBottom=ta.getDimension(R.styleable.CustomTabLayout_indicator_marginBottom,0f)
            mIndicatorWidth=ta.getDimension(R.styleable.CustomTabLayout_indicator_width,0f)
            mIndicatorWidthEqualTitle=ta.getBoolean(R.styleable.CustomTabLayout_indicator_width_equal_title,true)
            if(mIndicatorWidth>0f){
                mIndicatorWidthEqualTitle=false
            }
            mIndicatorColor=ta.getColor(R.styleable.CustomTabLayout_indicator_color,
                ColorUtil.getResourceColor(context,R.color.indicator))

            mTipsDefaultSize=ta.getDimension(R.styleable.CustomTabLayout_tab_tips_default_size, 16f.dp2px())
            mTipsTextSize=ta.getDimension(R.styleable.CustomTabLayout_tab_tips_text_size, 12f.dp2px())

            mTabPadddingLeft=ta.getDimension(R.styleable.CustomTabLayout_tab_padding_left,0f)
            mTabPadddingRight=ta.getDimension(R.styleable.CustomTabLayout_tab_padding_right,0f)

            ta.recycle()
        }

        mTabsContainer=LinearLayout(context)
        val lp=LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT)
        mTabsContainer.layoutParams=lp
        mTabsContainer.gravity=Gravity.CENTER
        addView(mTabsContainer)


    }


    fun showTips(position: Int,num:Int){
        if(position<0 || position>mTabsContainer.childCount-1) return
        val tab=mTabsContainer.getChildAt(position)
        val mtv=tab.findViewById<MsgTipsView>(R.id.common_mtv)
        mtv.visibility=View.VISIBLE
        mtv.setNum(num)
    }

    fun hideTips(position: Int){
        if(position<0 || position>mTabsContainer.childCount-1) return
        val tab=mTabsContainer.getChildAt(position)
        val mtv=tab.findViewById<MsgTipsView>(R.id.common_mtv)
        mtv.visibility=View.GONE
    }


    fun setViewPager(vp:ViewPager){

        if(vp.adapter==null){
            throw Throwable("viewpager adapter can not be null")
        }
        mTabCount = vp.adapter!!.count
        if(mTabCount==0){
            throw Throwable("viewpager adapter count can not be zero")
        }
        mViewPager=vp
        mTitles.clear()
        mTabsContainer.removeAllViews()



        for(i in 0 until mTabCount){
            addTab(i)
        }

        vp.addOnLayoutChangeListener(object :OnLayoutChangeListener{
            override fun onLayoutChange(
                v: View?,
                left: Int,
                top: Int,
                right: Int,
                bottom: Int,
                oldLeft: Int,
                oldTop: Int,
                oldRight: Int,
                oldBottom: Int
            ) {


            }

        })

        vp.addOnPageChangeListener(object : ViewPager.OnPageChangeListener{
            override fun onPageScrollStateChanged(state: Int) {
            }

            override fun onPageScrolled(
                    position: Int,
                    positionOffset: Float,
                    positionOffsetPixels: Int
            ) {
                mPositionOffset=positionOffset
                //attention: when show on first,tabview is not correct width

                if(position==0 && positionOffset==0f){
                    //init select
                    selectTab(0)
                    //LogUtil.log(position,positionOffset)
                    /*mCurrentPosition=position
                    selectTab(mCurrentPosition)
                    scrollToMiddle()*/

                }

                calculateIndicatorBounds(position)
                invalidate()

            }

            override fun onPageSelected(position: Int) {
                //onPageSelected will invoke on onPageScrolled() halfway
                if(mCurrentPosition!=position){
                    mCurrentPosition=position

                    selectTab(mCurrentPosition)
                    scrollToMiddle()

                    if(mPageChangeListener!=null)
                       mPageChangeListener!!(mCurrentPosition)
                }


            }
        })


        /*if(mShowIndicator){
            Handler(Looper.myLooper()!!).post {
                //selectTab(0)
                //calculateIndicatorBounds()
            }
        }
*/
        //init select first
        //selectTab(mCurrentPosition)

    }

    fun setOnPageChangeListener(listener:(Int)->Unit){
        mPageChangeListener=listener
    }


    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        val widthModel=MeasureSpec.getMode(widthMeasureSpec)
        var widthSize=MeasureSpec.getSize(widthMeasureSpec)
        val heightModel=MeasureSpec.getMode(heightMeasureSpec)
        var heightSize=MeasureSpec.getSize(heightMeasureSpec)

        /*if(widthModel==MeasureSpec.EXACTLY){
            val itemWidth=widthSize/mTabsContainer.childCount

            val itemHeightMeasure=MeasureSpec.makeMeasureSpec(measuredHeight,MeasureSpec.EXACTLY)


            LogUtil.log("aaa", measuredHeight)

            for(i in 0 until  mTabsContainer.childCount){
                val item=mTabsContainer[i]

                item.layoutParams.apply {
                    width=itemWidth
                }
                val itemWidthMeasure=MeasureSpec.makeMeasureSpec(itemWidth,MeasureSpec.EXACTLY)


                item.measure(itemWidthMeasure,itemHeightMeasure)

            }


        }*/
        if(heightModel!=MeasureSpec.EXACTLY && mTabHeight>0f){
            setMeasuredDimension(widthSize,mTabHeight.toInt())
        }

        //need to measure manually,otherwise bold font cannot get correct width
        if(mTabsContainer.childCount>0){
            if(mEvenWidth){
                val itemWidth=widthSize/mTabsContainer.childCount
                val itemHeightMeasure=MeasureSpec.makeMeasureSpec(measuredHeight,MeasureSpec.EXACTLY)

                for(i in 0 until mTabsContainer.childCount){
                    val item=mTabsContainer[i]
                    item.layoutParams.apply {
                        width=itemWidth
                    }
                    val itemWidthMeasure=MeasureSpec.makeMeasureSpec(itemWidth,MeasureSpec.EXACTLY)
                    item.measure(itemWidthMeasure,itemHeightMeasure)
                }
                val tabWidthMeasure=MeasureSpec.makeMeasureSpec(widthSize,MeasureSpec.EXACTLY)
                val tabHeightMeasure=MeasureSpec.makeMeasureSpec(measuredHeight,MeasureSpec.EXACTLY)
                mTabsContainer.measure(tabWidthMeasure,tabHeightMeasure)
            }else{
                if(mTabWidth>0f){
                    for(i in 0 until mTabsContainer.childCount){
                        val item=mTabsContainer[i]
                        val itemWidthMeasure=MeasureSpec.makeMeasureSpec(mTabWidth.toInt(),MeasureSpec.EXACTLY)
                        val itemHeightMeasure=MeasureSpec.makeMeasureSpec(measuredHeight,MeasureSpec.EXACTLY)
                        item.measure(itemWidthMeasure,itemHeightMeasure)
                    }
                    var tabContainerWidth=mTabWidth*mTabsContainer.childCount
                    val tabWidthMeasure=MeasureSpec.makeMeasureSpec(tabContainerWidth.toInt(),MeasureSpec.EXACTLY)
                    val tabHeightMeasure=MeasureSpec.makeMeasureSpec(measuredHeight,MeasureSpec.EXACTLY)
                    mTabsContainer.measure(tabWidthMeasure,tabHeightMeasure)
                }else{
                    var tabContainerWidth=0f
                    for(i in 0 until mTabsContainer.childCount){
                        val item=mTabsContainer[i]
                        val tabTitle=item.findViewById<TextView>(R.id.common_tv_tab_title)
                        val itemWidth=FontUtil.measureText(tabTitle.text.toString(),mTitleSelectSize,true)+mTabPadddingLeft+mTabPadddingRight
                        val itemWidthMeasure=MeasureSpec.makeMeasureSpec(itemWidth.toInt(),MeasureSpec.EXACTLY)
                        val itemHeightMeasure=MeasureSpec.makeMeasureSpec(measuredHeight,MeasureSpec.EXACTLY)
                        item.measure(itemWidthMeasure,itemHeightMeasure)
                        tabContainerWidth+=itemWidth
                    }
                    val tabWidthMeasure=MeasureSpec.makeMeasureSpec(tabContainerWidth.toInt(),MeasureSpec.EXACTLY)
                    val tabHeightMeasure=MeasureSpec.makeMeasureSpec(measuredHeight,MeasureSpec.EXACTLY)
                    mTabsContainer.measure(tabWidthMeasure,tabHeightMeasure)
                }

            }

        }



        //size may be unmeasure size,so need to determine set to correct size
       /* widthSize = with(ScreenUtil.getScreenWidth(context)){
            return@with if(widthSize>this) this else widthSize
        }*/

        /*if(widthModel!=MeasureSpec.EXACTLY){
            mEvenWidth=false
        }else{
            if(mTabsContainer.childCount>0){
                if(mTabWidth==0f && mEvenWidthAttr){
                    mEvenWidth=true*/

                   /* val itemWidth=widthSize/mTabsContainer.childCount
                    val itemHeightMeasure=MeasureSpec.makeMeasureSpec(measuredHeight,MeasureSpec.EXACTLY)

                    for(i in 0 until  mTabsContainer.childCount){
                        val item=mTabsContainer[i]
                        //prevent set many times
                        *//*if(item.width>0){
                            continue
                        }*//*
                        item.layoutParams.apply {
                            width=itemWidth
                        }
                        val itemWidthMeasure=MeasureSpec.makeMeasureSpec(itemWidth,MeasureSpec.EXACTLY)
                        item.measure(itemWidthMeasure,itemHeightMeasure)
                    }
                    val tabWidthMeasure=MeasureSpec.makeMeasureSpec(widthSize,MeasureSpec.EXACTLY)
                    val tabHeightMeasure=MeasureSpec.makeMeasureSpec(measuredHeight,MeasureSpec.EXACTLY)
                    mTabsContainer.measure(tabWidthMeasure,tabHeightMeasure)*/

                //}
           // }

        //}

    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        super.onLayout(changed, l, t, r, b)
        //LogUtil.log("onLayout",l,t,r,b)

    }


    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
       // LogUtil.log("onSizeChanged",w,h,oldw,oldh)
        super.onSizeChanged(w, h, oldw, oldh)

    }

    private fun scrollToMiddle(){
        if(mTabsContainer.size-1<mCurrentPosition) return
        mViewPager?.let {
            val tabView= mTabsContainer[mCurrentPosition]
            //var x=tabView.left-ScreenUtil.getScreenWidth()/2+tabView.width/2
            var x=tabView.left-width/2+tabView.width/2
            //scrollTo(x,0)
            smoothScrollTo(x,0)

        }
    }

    private fun getTab(i:Int):View?{
        if(mTabsContainer.childCount-1>=i){
            return mTabsContainer[i]
        }
        return null
    }

    private fun addTab(i:Int){
        val tabView=LayoutInflater.from(context).inflate(R.layout.common_item_custom_tab,mTabsContainer,false)
        tabView.layoutParams=LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT)

        val rlTab=tabView.findViewById<ConstraintLayout>(R.id.common_rl_tab)
        val tabTitle=tabView.findViewById<TextView>(R.id.common_tv_tab_title)
        val tabTips=tabView.findViewById<MsgTipsView>(R.id.common_mtv)
        rlTab.setPadding(mTabPadddingLeft.toInt(),0,mTabPadddingLeft.toInt(),0)

        tabTips.textSize=mTipsTextSize.px2sp()
        tabTips.setDefaultSize(mTipsDefaultSize)

        mDefaultTextSize=tabTitle.textSize

        if(mTabWidth>0f){
            //tabView.layoutParams.width=mTabWidth.toInt()
            tabView.layoutParams=tabView.layoutParams.apply {
                width=mTabWidth.toInt()
            }
            //mEventScreen=false
        }else{
            if(mEvenWidth){
              /* tabView.layoutParams=tabView.layoutParams.apply {
                    width=measuredWidth/mTabCount
                }*/
            }
        }

        if(mTabHeight>0){
            //tabView.layoutParams.height=mTabHeight.toInt()
            tabView.layoutParams=tabView.layoutParams.apply {
                height=mTabHeight.toInt()
            }
        }else{

            val tabTitle=tabView.findViewById<TextView>(R.id.common_tv_tab_title)
            //val bounds = getTextBounds(tabTitle.text.toString(),if(mTitleSelectSize>0f) mTitleSelectSize else mDefaultTextSize,true) ?: return
            val bounds=FontUtil.getTextBounds(tabTitle.text.toString(),if(mTitleSelectSize>0f) mTitleSelectSize else mDefaultTextSize,true)?:return
            //LogUtil.log(bounds.top,bounds.bottom,bounds.bottom-bounds.top)
            var h=(bounds.bottom-bounds.top)

            if(mShowIndicator){
                h+=((mIndicatorHeight+mIndicatorMarginTop+mIndicatorMarginBottom)*2).toInt()
            }

            tabView.layoutParams=tabView.layoutParams.apply {
                height=h
            }

        }

        mTabsContainerHeight=tabView.layoutParams.height

        //tabView.setBackgroundColor(mTabBackGroundColor)

        val title=mViewPager!!.adapter!!.getPageTitle(i).toString()


        mTitles.add(title)
        tabTitle.text=(title)
        tabTitle.setTextColor(mTitleColor)

        if(mTitleSize>0f)
            tabTitle.textSize=mTitleSize.px2sp()

        //setTitleMarginTop(tabTitle)

        tabView.setOnClickListener{
            if(mViewPager?.currentItem==i){
                return@setOnClickListener
            }
            selectTab(i)
        }

        if(mTitleSize>0f){
            tabTitle.textSize=mTitleSize.px2sp()
        }

        mTabsContainer.addView(tabView)


    }

    /* private fun setTitleMarginTop(tabTitle:TextView){
        val bounds = getTextBounds(tabTitle) ?: return

         //center
         val titleTop=(mTabsContainerHeight-(bounds.bottom-bounds.top+mIndicatorHeight)+mIndicatorMarginTop+mIndicatorMarginBottom)/2
         (tabTitle.layoutParams as RelativeLayout.LayoutParams).topMargin=titleTop.toInt()

     }*/



    fun selectTab(i:Int){
        if(i<0) return
        if(mTabsContainer.childCount-1<i) return

        //if(i>0 && i==mCurrentPosition) return

        val tabView=mTabsContainer[i]
        //draw select color in ondraw(),otherwise will cover indicator
        tabView.setBackgroundColor(Color.TRANSPARENT)
        calculateSelectBackgroundBounds(i)
        val tabTitle=tabView.findViewById<TextView>(R.id.common_tv_tab_title)
        //val defaultTextSize=tabTitle.textSize

        mViewPager?.currentItem=i

        //select style
        tabTitle.typeface=Typeface.defaultFromStyle(Typeface.BOLD)
        tabTitle.setTextColor(mTitleSelectColor)
        if(mTitleSelectSize>0f)
            tabTitle.textSize=mTitleSelectSize.px2sp()

        //unselect style
        for(j in 0 until mViewPager!!.adapter!!.count){
            if(j!=i && mTabsContainer.childCount-1>=j){
                val tv=mTabsContainer[j]
                tv.setBackgroundColor(mTabBackGroundColor)

                val tt=tv.findViewById<TextView>(R.id.common_tv_tab_title)
                tt.typeface=Typeface.defaultFromStyle(Typeface.NORMAL)
                tt.setTextColor(mTitleColor)
                if(mTitleSize>0f){
                    tt.textSize=mTitleSize.px2sp()
                }else{
                    tt.textSize=mDefaultTextSize.px2sp()
                }

            }
        }

       /* for(i in 0 until mTabsContainer.childCount){
            val item=mTabsContainer[i]
             if(i%2==0){
                 item.setBackgroundColor(Color.RED)
               }else{
                 item.setBackgroundColor(Color.GREEN)
               }
        }*/


        // calculateIndicatorBounds()

    }

    private fun calculateSelectBackgroundBounds(position:Int){
        if(mTabSelectBackGroundColor==Color.TRANSPARENT || mTabCount==0) return
        val tabView=mTabsContainer[position]
        var left=tabView.left
        var top=tabView.top
        var right=tabView.right
        var bottom=tabView.bottom


        mSelectBackGroundBounds.apply {
            this.left=left
            this.top=top
            this.right=right
            this.bottom=bottom
        }
    }

    private fun calculateIndicatorBounds(position:Int){
        if(!mShowIndicator || mTabCount==0) return

        val tabView=mTabsContainer[position]

        val tabTitle=tabView.findViewById<TextView>(R.id.common_tv_tab_title)

        val bounds = FontUtil.getTextBounds(tabTitle.text.toString(),if(mTitleSelectSize>0f) mTitleSelectSize else mDefaultTextSize,true) ?: return

        var left=0
        var top=0
        var right=0
        var bottom=0

        top=(tabView.height-(tabView.height-(bounds.bottom-bounds.top))/2+mIndicatorMarginTop).toInt()

        bottom=(top+mIndicatorHeight-mIndicatorMarginBottom).toInt()
        if(mIndicatorWidthEqualTitle){
            left=(tabView.width-(bounds.right-bounds.left))/2
            right=left+(bounds.right-bounds.left)
        }else{
            if(mIndicatorWidth>0f){
                left=((tabView.width-mIndicatorWidth)/2).toInt()
                right=left+mIndicatorWidth.toInt()
            }
        }


        val offset=(tabView.width*mPositionOffset).toInt()

        left+=tabView.left+offset
        right+=tabView.left+offset

        //LogUtil.log("aaa",position,tabView.width)

        mIndicatorBounds.apply {
            this.left=left
            this.top=top
            this.right=right
            this.bottom=bottom
        }

    }

    override fun onDraw(canvas: Canvas?) {

        super.onDraw(canvas)

        if(canvas==null || mTabCount<=0) return

        if(mTabSelectBackGroundColor!=Color.TRANSPARENT){
            val mSelectBackGroundDrawable=GradientDrawable()
            mSelectBackGroundDrawable.bounds=mSelectBackGroundBounds
            mSelectBackGroundDrawable.setColor(mTabSelectBackGroundColor)
            mSelectBackGroundDrawable.draw(canvas)
        }


        if(mShowIndicator){
            mIndicatorDrawable.bounds=mIndicatorBounds

            mIndicatorDrawable.setColor(mIndicatorColor)
            if(mIndicatorRadius>0f){
                mIndicatorDrawable.cornerRadius=mIndicatorRadius
            }
            mIndicatorDrawable.draw(canvas)
        }

    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        selectTab(mViewPager?.currentItem?:0)
    }


    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        selectTab(mViewPager?.currentItem?:0)
    }


    override fun onConfigurationChanged(newConfig: Configuration?) {
        super.onConfigurationChanged(newConfig)
        //prohibit change screen orientation
        //LogUtil.log("onConfigurationChanged",newConfig?.orientation)
        //calculateIndicatorBounds(0)

        //invalidate()
    }


    /*override fun onFinishInflate() {
        super.onFinishInflate()
        //LogUtil.log("onFinishInflate",mTabsContainer[0].width)
    }*/


}